package org.dxy.trigger.http.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dxy.api.dto.request.workstation.CreateWorkstationRequestDto;
import org.dxy.api.dto.request.workstation.UpdateWorkstationRequestDto;
import org.dxy.api.dto.request.workstation.WorkstationOutRequest;
import org.dxy.api.dto.response.R;
import org.dxy.api.dto.request.workstation.WorkstationInRequest;
import org.dxy.api.dto.vo.WorkstationOperationVo;
import org.dxy.api.dto.vo.WorkstationReportVo;
import org.dxy.api.dto.vo.WorkstationRuntimeStatusVo;
import org.dxy.domain.command.workstation.WorkstationInCommand;
import org.dxy.domain.command.workstation.WorkstationOutCommand;
import org.dxy.domain.handler.workstation.WorkstationInCommandHandler;
import org.dxy.domain.handler.workstation.WorkstationOutCommandHandler;
import org.dxy.infrastructure.persistent.po.query.ProductViewPo;
import org.dxy.infrastructure.persistent.po.query.ProductionLineBasicViewPo;
import org.dxy.infrastructure.persistent.po.query.WorkstationBasicViewPo;
import org.dxy.infrastructure.persistent.po.query.WorkstationRuntimeViewPo;
import org.dxy.infrastructure.persistent.service.*;
import org.dxy.trigger.http.service.ProductApplicationService;
import org.dxy.types.common.CommandResult;
import org.dxy.trigger.http.service.WorkstationApplicationService;
import org.dxy.types.enums.WorkstationStatusEnum;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.ArrayList;

/**
 * 工位应用服务实现类
 * @author dxy
 * @createTime 2025/9/4
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class WorkstationApplicationServiceImpl implements WorkstationApplicationService {
    
    private final WorkstationBasicViewService workstationBasicViewService;
    private final ProductionLineBasicViewService productionLineBasicViewService;
    private final WorkstationRuntimeViewService workstationRuntimeViewService;
    private final WorkstationInCommandHandler workstationInCommandHandler;
    private final WorkstationOutCommandHandler workstationOutCommandHandler;
    private final ProductViewService productViewService;
    private final WorkOrderViewService workOrderViewService;


    private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    @Transactional
    @Override
    public R<Void> createWorkstation(CreateWorkstationRequestDto dto) {
        try {
            log.info("开始创建工位: workstationCode={}, workstationName={}, productionLineId={}", 
                    dto.getWorkstationCode(), dto.getWorkstationName(), dto.getProductionLineId());
            
            // 检查产线是否存在
            ProductionLineBasicViewPo productionLine = productionLineBasicViewService.getById(dto.getProductionLineId());
            if (productionLine == null) {
                return R.fail("所属产线不存在");
            }
            
            // 检查工位编码是否已存在
            // TODO: 需要实现工位编码唯一性检查
            
            // 构建位置信息
            String location = buildLocation(productionLine.getFactoryName(), 
                    productionLine.getWorkshopName(), 
                    productionLine.getLineName(), 
                    dto.getWorkstationName());
            
            // 创建工位实体
            WorkstationBasicViewPo workstation = WorkstationBasicViewPo.builder()
                    .workstationCode(dto.getWorkstationCode())
                    .workstationName(dto.getWorkstationName())
                    .productionLineId(dto.getProductionLineId())
//                    .productionLineName(productionLine.getLineName())
                    .workshopId(productionLine.getWorkshopId())
//                    .workshopName(productionLine.getWorkshopName())
                    .factoryId(productionLine.getFactoryId())
//                    .factoryName(productionLine.getFactoryName())
                    .workstationType(dto.getWorkstationType())
                    .status(StringUtils.hasText(dto.getStatus()) ? dto.getStatus() : "IDLE")
//                    .capacity(dto.getCapacity())
                    .position(dto.getPosition())
//                    .location(location)
//                    .supportedProcessTypes(dto.getSupportedProcessTypes())
                    .description(dto.getDescription())
                    .build();
            
            workstationBasicViewService.save(workstation);
            
            log.info("工位创建成功: workstationId={}", workstation.getId());
            return R.ok("工位创建成功");
            
        } catch (Exception e) {
            log.error("创建工位失败", e);
            return R.fail("创建工位失败: " + e.getMessage());
        }
    }

    @Override
    public R<Page<WorkstationBasicViewPo>> page(Page<WorkstationBasicViewPo> page, WorkstationBasicViewPo query) {
        try {
            Page<WorkstationBasicViewPo> result = workstationBasicViewService.pageWorkstationView(
                page,
                query != null ? query.getFactoryId() : null,
                query != null ? query.getWorkshopId() : null,
                query != null ? query.getProductionLineId() : null,
                query != null ? query.getWorkstationCode() : null,
                query != null ? query.getWorkstationName() : null,
                query != null ? query.getStatus() : null
            );
            return R.ok(result, "查询成功");
            
        } catch (Exception e) {
            log.error("查询工位列表失败", e);
            return R.fail("查询工位列表失败: " + e.getMessage());
        }
    }

    @Transactional
    @Override
    public R<Void> update(Long id, UpdateWorkstationRequestDto dto) {
        try {
            log.info("开始更新工位: workstationId={}", id);
            
            WorkstationBasicViewPo workstation = workstationBasicViewService.getById(id);
            if (workstation == null) {
                return R.fail("工位不存在");
            }
            
            // 检查产线是否存在
            ProductionLineBasicViewPo productionLine = productionLineBasicViewService.getById(dto.getProductionLineId());
            if (productionLine == null) {
                return R.fail("所属产线不存在");
            }
            
            // 构建位置信息
            String location = buildLocation(productionLine.getFactoryName(), 
                    productionLine.getWorkshopName(), 
                    productionLine.getLineName(), 
                    dto.getWorkstationName());
            
            // 更新工位信息
            workstation.setWorkstationName(dto.getWorkstationName());
            workstation.setProductionLineId(dto.getProductionLineId());
//            workstation.setProductionLineName(productionLine.getLineName());
            workstation.setWorkshopId(productionLine.getWorkshopId());
//            workstation.setWorkshopName(productionLine.getWorkshopName());
            workstation.setFactoryId(productionLine.getFactoryId());
//            workstation.setFactoryName(productionLine.getFactoryName());
            workstation.setWorkstationType(dto.getWorkstationType());
            workstation.setStatus(dto.getStatus());
//            workstation.setCapacity(dto.getCapacity());
            workstation.setPosition(dto.getPosition());
//            workstation.setLocation(location);
//            workstation.setSupportedProcessTypes(dto.getSupportedProcessTypes());
            workstation.setDescription(dto.getDescription());

            workstationBasicViewService.updateById(workstation);
            
            log.info("工位更新成功: workstationId={}", id);
            return R.ok("工位更新成功");
            
        } catch (Exception e) {
            log.error("更新工位失败, workstationId={}", id, e);
            return R.fail("更新工位失败: " + e.getMessage());
        }
    }

    @Transactional
    @Override
    public R<Void> delete(Long id) {
        try {
            log.info("开始删除工位: workstationId={}", id);
            
            WorkstationBasicViewPo workstation = workstationBasicViewService.getById(id);
            if (workstation == null) {
                return R.fail("工位不存在");
            }
            
            // TODO: 检查是否有关联的设备或任务
            
            workstationBasicViewService.removeById(id);
            
            log.info("工位删除成功: workstationId={}", id);
            return R.ok("工位删除成功");
            
        } catch (Exception e) {
            log.error("删除工位失败, workstationId={}", id, e);
            return R.fail("删除工位失败: " + e.getMessage());
        }
    }

    @Transactional
    @Override
    public R<Void> batchDelete(List<Long> ids) {
        try {
            log.info("开始批量删除工位: workstationIds={}", ids);
            
            if (ids == null || ids.isEmpty()) {
                return R.fail("工位ID列表不能为空");
            }
            
            // TODO: 检查是否有关联的设备或任务
            
            workstationBasicViewService.removeByIds(ids);
            
            log.info("批量删除工位成功: count={}", ids.size());
            return R.ok("批量删除工位成功");
            
        } catch (Exception e) {
            log.error("批量删除工位失败, workstationIds={}", ids, e);
            return R.fail("批量删除工位失败: " + e.getMessage());
        }
    }

    @Override
    public R<WorkstationBasicViewPo> getById(Long id) {
        try {
            WorkstationBasicViewPo workstation = workstationBasicViewService.getWorkstationViewById(id);
            if (workstation != null) {
                return R.ok(workstation, "查询成功");
            } else {
                return R.fail("工位不存在");
            }
        } catch (Exception e) {
            log.error("查询工位详情失败, workstationId={}", id, e);
            return R.fail("查询工位详情失败: " + e.getMessage());
        }
    }

    @Override
    public R<List<WorkstationBasicViewPo>> getByProductionLineId(Long productionLineId) {
        try {
            List<WorkstationBasicViewPo> workstations = workstationBasicViewService.listWorkstationViewByProductionLineId(productionLineId);
            return R.ok(workstations, "查询成功");
        } catch (Exception e) {
            log.error("根据产线ID查询工位列表失败, productionLineId={}", productionLineId, e);
            return R.fail("根据产线ID查询工位列表失败: " + e.getMessage());
        }
    }

    @Override
    public R<List<WorkstationBasicViewPo>> getEnabledByProductionLineId(Long productionLineId) {
        try {
            log.info("开始查询产线下启用状态的工位列表: productionLineId={}", productionLineId);
            
            // 检查产线是否存在
            ProductionLineBasicViewPo productionLine = productionLineBasicViewService.getById(productionLineId);
            if (productionLine == null) {
                return R.fail("所属产线不存在");
            }
            
            // 查询产线下的所有工位，然后过滤启用状态的
            List<WorkstationBasicViewPo> allWorkstations = workstationBasicViewService.listWorkstationViewByProductionLineId(productionLineId);
            List<WorkstationBasicViewPo> enabledWorkstations = allWorkstations.stream()
                    .filter(ws -> !"DISABLED".equals(ws.getStatus()))
                    .toList();
            
            log.info("查询产线下启用状态的工位列表成功: productionLineId={}, count={}", productionLineId, enabledWorkstations.size());
            return R.ok(enabledWorkstations, "查询成功");
            
        } catch (Exception e) {
            log.error("根据产线ID查询启用状态的工位列表失败, productionLineId={}", productionLineId, e);
            return R.fail("根据产线ID查询启用状态的工位列表失败: " + e.getMessage());
        }
    }

    @Override
    public R<List<WorkstationBasicViewPo>> getAllEnabledWorkstations() {
        try {
            log.info("开始查询所有启用状态的工位列表");
            
            // 查询所有工位，然后过滤启用状态的
            List<WorkstationBasicViewPo> allWorkstations = workstationBasicViewService.listAllWorkstationView();
            List<WorkstationBasicViewPo> enabledWorkstations = allWorkstations.stream()
                    .filter(ws -> WorkstationStatusEnum.IDLE.getKey().equals(ws.getStatus()))
                    .toList();
            
            log.info("查询所有启用状态的工位列表成功: count={}", enabledWorkstations.size());
            return R.ok(enabledWorkstations, "查询成功");
            
        } catch (Exception e) {
            log.error("查询所有启用状态的工位列表失败", e);
            return R.fail("查询所有启用状态的工位列表失败: " + e.getMessage());
        }
    }

    @Override
    public R<List<WorkstationBasicViewPo>> getAvailableWorkstationsForIn() {
        try {
            log.info("开始查询可进站的工位列表（空闲状态）");
            
            // 查询所有工位，然后过滤空闲状态的
            List<WorkstationBasicViewPo> allWorkstations = workstationBasicViewService.listAllWorkstationView();
            List<WorkstationBasicViewPo> availableWorkstations = allWorkstations.stream()
                    .filter(ws -> WorkstationStatusEnum.IDLE.getKey().equals(ws.getStatus()))
                    .toList();
            
            log.info("查询可进站的工位列表成功: count={}", availableWorkstations.size());
            return R.ok(availableWorkstations, "查询成功");
            
        } catch (Exception e) {
            log.error("查询可进站的工位列表失败", e);
            return R.fail("查询可进站的工位列表失败: " + e.getMessage());
        }
    }

    @Override
    public R<List<WorkstationBasicViewPo>> getAvailableWorkstationsForOut() {
        try {
            log.info("开始查询可出站的工位列表（运行中状态）");
            
            // 查询所有工位，然后过滤运行中状态的
            List<WorkstationBasicViewPo> allWorkstations = workstationBasicViewService.listAllWorkstationView();
            List<WorkstationBasicViewPo> availableWorkstations = allWorkstations.stream()
                    .filter(ws -> WorkstationStatusEnum.RUNNING.getKey().equals(ws.getStatus()))
                    .toList();
            
            log.info("查询可出站的工位列表成功: count={}", availableWorkstations.size());
            return R.ok(availableWorkstations, "查询成功");
            
        } catch (Exception e) {
            log.error("查询可出站的工位列表失败", e);
            return R.fail("查询可出站的工位列表失败: " + e.getMessage());
        }
    }
    
    // ==================== 工位操作相关方法 ====================
    
    /**
     * 工位进站
     */
    public  R<String> stationIn(WorkstationInRequest request) {
        // 1. 转换：code → ID（外部适配）
        Long workstationId = workstationBasicViewService.findIdByCode(request.getWorkstationCode());
        Long productId = productViewService.findIdByCode(request.getProductCode());
        Long workOrderId = workOrderViewService.findIdByProductId(productId);

        // 2. 构建 Command
        WorkstationInCommand command = WorkstationInCommand.builder()
                .workstationId(workstationId)
                .carrierCode(request.getCarrierCode())
                .productId(productId)
                .workOrderId(workOrderId)
                .build();

        // 3. 委托 Handler
        CommandResult<Void> commandResult = workstationInCommandHandler.handle(command);
        boolean success = commandResult.success();
        String msg = commandResult.msg();
        if (success) {  // 或 result.success()，两者等价
            return R.ok(msg);
        } else {
            return R.fail(msg);
        }
    }

    /**
     * 工位出站
     */
    public R<String> stationOut(WorkstationOutRequest request) {
        log.info("处理工位出站请求: request: {}", request);

        WorkstationOutCommand command = WorkstationOutCommand.builder().build();
        CommandResult<Long> commandResult = workstationOutCommandHandler.handle(command);
        boolean success = commandResult.success();
        String msg = commandResult.msg();
        if (success) {
            return R.ok(msg);
        } else {
            return R.fail(msg);
        }
    }

    /**
     * 查询工位操作记录
     */
    public List<WorkstationOperationVo> queryOperationRecords(Long workstationId, String workOrderCode, 
                                                              LocalDateTime startTime, LocalDateTime endTime) {
        // TODO: 实现操作记录查询逻辑
        return List.of();
    }

    /**
     * 查询工位报表
     */
    public List<WorkstationReportVo> queryWorkstationReport(Long workstationId, LocalDate startDate, LocalDate endDate) {
        // TODO: 实现工位报表查询逻辑
        return List.of();
    }

    /**
     * 查询实时状态
     */
    public List<WorkstationRuntimeStatusVo> queryRealTimeStatus() {
        try {
            log.info("开始查询工位实时运行状态");
            
            // 获取所有工位的运行时状态
            List<WorkstationRuntimeViewPo> runtimeList = workstationRuntimeViewService.getAllRuntimeStatus();
            
            // 转换为VO
            List<WorkstationRuntimeStatusVo> statusList = new ArrayList<>();
            for (WorkstationRuntimeViewPo runtime : runtimeList) {
                WorkstationRuntimeStatusVo statusVo = convertToRuntimeStatusVo(runtime);
                statusList.add(statusVo);
            }
            
            log.info("查询工位实时运行状态成功: count={}", statusList.size());
            return statusList;
            
        } catch (Exception e) {
            log.error("查询工位实时运行状态失败", e);
            return List.of();
        }
    }
    
    /**
     * 转换WorkstationRuntimeViewPo为WorkstationRuntimeStatusVo
     */
    private WorkstationRuntimeStatusVo convertToRuntimeStatusVo(WorkstationRuntimeViewPo runtime) {
        WorkstationRuntimeStatusVo statusVo = new WorkstationRuntimeStatusVo();
        statusVo.setWorkstationId(runtime.getWorkstationId());
        statusVo.setCurrentOperationId(runtime.getCurrentOperationId());
        statusVo.setCurrentWorkOrderCode(runtime.getCurrentWorkOrderCode());
        statusVo.setSerialNumber(runtime.getSerialNumber());
        statusVo.setCurrentInTime(runtime.getCurrentInTime());
        statusVo.setCurrentOutTime(runtime.getCurrentOutTime());
        statusVo.setStatus(runtime.getCurrentStatus());
        statusVo.setOperatorName(runtime.getCurrentOperatorName());
        
        // 获取工位基础信息
        try {
            WorkstationBasicViewPo workstation = workstationBasicViewService.getById(runtime.getWorkstationId());
            if (workstation != null) {
                statusVo.setWorkstationName(workstation.getWorkstationName());
                statusVo.setWorkstationCode(workstation.getWorkstationCode());
            }
        } catch (Exception e) {
            log.warn("获取工位基础信息失败: workstationId={}", runtime.getWorkstationId(), e);
        }
        
        // 计算运行时长
        if (runtime.getCurrentInTime() != null && "IN_PROGRESS".equals(runtime.getCurrentStatus())) {
            Duration duration = Duration.between(runtime.getCurrentInTime(), LocalDateTime.now());
            statusVo.setRunningDuration((int) duration.toMinutes());
        }
        
        return statusVo;
    }
    
    /**
     * 构建位置信息
     */
    private String buildLocation(String factoryName, String workshopName, String lineName, String workstationName) {
        return String.format("%s-%s-%s-%s", factoryName, workshopName, lineName, workstationName);
    }
}